package cn.sdc.bugKiller.util;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Properties;
import java.util.logging.Logger;

import javax.sql.DataSource;

import cn.sdc.sfw.dao.handler.SelectHandler;
import cn.sdc.sfw.dao.handler.UpdateHandler;
import cn.sdc.sfw.dao.handler.impl.BeanResultSetHandlerImpl;
import cn.sdc.sfw.dao.handler.impl.ObjectResultSetHandlerImpl;
import cn.sdc.sfw.dao.handler.impl.SelectHandlerImpl;
import cn.sdc.sfw.dao.handler.impl.UpdateHandlerImpl;

public class DbUtil {
	private String driver;// 定义驱动
	private String url;// 定义URL
	private String user;// 定义用户名
	private String password;// 定义密码
	
	private DataSource dataSource;
	private Connection conn;// 定义连接
//	private Statement stmt;// 定义STMT
//	private ResultSet rs;// 定义结果集

	
	private static DbUtil INSTANCE;
	private static String JDBC_FILE_PATH;
	
	public static DbUtil getInstance(){
		if(INSTANCE == null){
			INSTANCE = new DbUtil(JDBC_FILE_PATH);
		}
		return INSTANCE;
	}
	
	public static DataSource getDsInstance(String conf){
		if(INSTANCE == null){
			INSTANCE = new DbUtil(JDBC_FILE_PATH);
		}
		return INSTANCE.getDataSource();
	}
	
	public DataSource getDataSource(){
		return dataSource;
	}
	
	public static void setJdbcFilePath(String path){
		JDBC_FILE_PATH = path;
	}
	
	// 有参构造函数，传入路径Conf并用方法loadProperties进行加载，用setConn进行设置
	public DbUtil(String conf) {
		loadProperties(conf);
		setDataSource();
		setConn();
	}
	
	private void setDataSource() {
		dataSource = new BugDataSource(driver,url,user,password);
	}

	// 返回Conn
	public Connection getConn() throws SQLException {
		//return this.conn;
		return dataSource.getConnection();
	}

	// 传入参数路径Conf加载配置文件取得配置文件中的参数并设置为类变量的参数
	private void loadProperties(String conf) {
		Properties props = new Properties();
		try {
			props.load(new FileInputStream(conf));// 根据配置文件路径Conf加载配置文件
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		this.driver = props.getProperty("driverClassName");// 从配置文件中取得相应的参数并设置类变量
		this.url = props.getProperty("url");
		this.user = props.getProperty("username");
		this.password = props.getProperty("password");
	}

	// 设置CONN
	private void setConn() {
		
		try {
			conn = dataSource.getConnection();
			/*
			Class.forName(driver);
			this.conn = DriverManager.getConnection(url, user, password);
		} catch (ClassNotFoundException classnotfoundexception) {
			classnotfoundexception.printStackTrace();
			System.err.println("db: " + classnotfoundexception.getMessage());
			*/
		} catch (SQLException sqlexception) {
			System.err.println("db.getconn(): " + sqlexception.getMessage());
		}
	}

	// 执行带参数更新
	public int doUpdate(String sql, Object[] args, Class[] argTypes) {
		UpdateHandler updhandler = new UpdateHandlerImpl(dataSource,sql);
		return updhandler.execute(args,argTypes);
	}
	public int doUpdate(String sql, Object[] args) {
		UpdateHandler updhandler = new UpdateHandlerImpl(dataSource,sql);
		return updhandler.execute(args);
	}
	
	// 执行更新
	public int doUpdate(String sql) {
		UpdateHandler updhandler = new UpdateHandlerImpl(dataSource,sql);
		return updhandler.execute();
	}

	// 查询结果集
	public Object doSelectObject(String sql) {
		SelectHandler handler = new SelectHandlerImpl(dataSource,
				sql, new ObjectResultSetHandlerImpl());
		return handler.execute();
	}
	public Object doSelectObject(String sql, Object[] args) {
		SelectHandler handler = new SelectHandlerImpl(dataSource,
				sql, new ObjectResultSetHandlerImpl());
		return handler.execute(args);
	}
	public Object doSelectObject(String sql, Object[] args, Class[] argTypes) {
		SelectHandler handler = new SelectHandlerImpl(dataSource,
				sql, new ObjectResultSetHandlerImpl());
		return handler.execute(args, argTypes);
	}
	
	// 查询结果集(Bean)
	public Object doSelectBean(Class beanClass, String sql) {
		SelectHandler handler = new SelectHandlerImpl(dataSource,
				sql, new BeanResultSetHandlerImpl(beanClass));
		return handler.execute();
	}
	public Object doSelectBean(Class beanClass, String sql, Object[] args) {
		SelectHandler handler = new SelectHandlerImpl(dataSource,
				sql, new BeanResultSetHandlerImpl(beanClass));
		return handler.execute(args);
	}
	
	public Object doSelectBean(Class beanClass, String sql, Object[] args, Class[] argTypes) {
		SelectHandler handler = new SelectHandlerImpl(dataSource,
				sql, new BeanResultSetHandlerImpl(beanClass));
		return handler.execute(args,argTypes);
	}
	
	// 查询结果集(BeanList)
	public Object doSelectBeanList(Class beanClass, String sql) {
		SelectHandler handler = new SelectHandlerImpl(dataSource,
				sql, new BeanResultSetHandlerImpl(beanClass,true));
		return handler.execute();
	}
	public Object doSelectBeanList(Class beanClass, String sql, Object[] args) {
		SelectHandler handler = new SelectHandlerImpl(dataSource,
				sql, new BeanResultSetHandlerImpl(beanClass,true));
		return handler.execute(args);
	}
	public Object doSelectBeanList(Class beanClass, String sql, Object[] args, Class[] argTypes) {
		SelectHandler handler = new SelectHandlerImpl(dataSource,
				sql, new BeanResultSetHandlerImpl(beanClass,true));
		return handler.execute(args,argTypes);
	}
	
	/*
	// 执行更新
	public void doUpdate(String sql) {
		try {
			stmt = conn.createStatement();
			int i = stmt.executeUpdate(sql);
		} catch (SQLException sqlexception) {
			System.err.println("db.executeUpdate:" + sqlexception.getMessage());
		}
	}

	// 查询结果集
	public ResultSet doSelect(String sql) {
		try {
			stmt = conn.createStatement(
					java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,
					java.sql.ResultSet.CONCUR_READ_ONLY);
			rs = stmt.executeQuery(sql);
		} catch (SQLException sqlexception) {
			System.err.println("db.executeQuery: " + sqlexception.getMessage());
		}
		return rs;
	}
	*/
	
	/**
	 * 关闭数据库操作对象，数据库连接对象 Close all the statement and conn int this instance
	 * 
	 * @throws SQLException
	 * @throws Exception
	 */
	public void close(){
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			conn = null;
		}
	}
	
	/**
	 * 提交事务
	 * 
	 * @throws SQLException
	 * @throws Exception
	 */
	public void commit() {
		if (conn != null) {
			try {
				conn.commit();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 回滚事务
	 * 
	 * @throws SQLException
	 * @throws Exception
	 */
	public void rollback() {
		if (conn != null) {
			try {
				conn.rollback();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

class BugDataSource implements DataSource{

	String drivername, url, user, password;
	Connection connection;
	
	public BugDataSource() {
	}
	
	public BugDataSource(String drivername, String url, String user,
			String password) {
		super();
		this.drivername = drivername;
		this.url = url;
		this.user = user;
		this.password = password;
	}

	public Connection getConnection() throws SQLException {
		
		if(connection != null){
			return connection;
		}
		
		try {
			Class.forName(drivername);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			return null;
		}
		connection = DriverManager.getConnection(url,user,password);
		connection.setAutoCommit(false);
		return connection;
	}

	public Connection getConnection(String user, String password)
		throws SQLException {
		this.user = user;
		this.password = password;
		return getConnection();
	}

	public void setLoginTimeout(int loginTimeout) throws SQLException {
	}

	public int getLoginTimeout() throws SQLException {
		return 0;
	}

	public void setLogWriter(PrintWriter logWriter) throws SQLException {
	}

	public PrintWriter getLogWriter() throws SQLException {
		return null;
	}

	@Override
	public <T> T unwrap(Class<T> iface) throws SQLException {
		return null;
	}

	@Override
	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		return false;
	}

	@Override
	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
		// TODO Auto-generated method stub
		return null;
	}
}

